package com.uplift.mgt.building.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.uplift.common.Const;
import com.uplift.common.base.BusinessException;
import com.uplift.common.base.ServiceReslut;
import com.uplift.common.utils.JExcelReadUtils;
import com.uplift.common.utils.ZipUtil;
import com.uplift.mgt.building.dao.RealtyInfoMapper;
import com.uplift.mgt.building.dao.RealtyRoomMapper;
import com.uplift.mgt.building.model.RealtyInfo;
import com.uplift.mgt.building.model.RealtyRoomModel;
import com.uplift.mgt.building.service.IRealtyInfoService;
import com.uplift.mgt.building.service.IRealtyRoomService;
import com.uplift.mgt.customer.dao.CustomerMapper;
import com.uplift.mgt.customer.model.Customer;
import com.uplift.mgt.customer.service.ICustomerService;
import com.uplift.mgt.sys.model.DictModel;
import com.uplift.mgt.sys.service.IDictService;
import com.uplift.sec.SecurityContext;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.lang3.StringUtils;
import org.omg.CORBA.OBJ_ADAPTER;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import java.io.*;
import java.math.BigDecimal;
import java.nio.charset.Charset;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

@Service
@Transactional
public class RealtyInfoServiceImpl implements IRealtyInfoService {

	@Autowired
	private RealtyInfoMapper realtyInfoMapper;

	@Autowired
	private ICustomerService customerService;
	@Autowired
	private IDictService dictService;

	@Autowired
	private RealtyRoomMapper realtyRoomMapper;

	private List<Map<String, Object>> gzCodeMap;

	/** excle 每列的字段名称 */
	private String[] excel_cloum_names = new String[] {"客户名称","公寓类型","楼盘名称","房间号","楼盘地址","楼盘图片",
			"购入价格","建筑年月","构造","楼层","火灾/地震险","专用面积","固都税","管理费","修缮金","土地面积（一栋）",
	        "建筑面积（一栋）","地域用途（一栋）","建筑率（一栋）","容积率（一栋）"};

	@Override
	public List<Map<String, Object>> queryRealtyInfo(RealtyInfo realtyInfo) {
		PageHelper.startPage(realtyInfo.getPage(), realtyInfo.getLimit());
		return this.realtyInfoMapper.selectRealtyInfo(realtyInfo);
	}
	@Override
	public List<Map<String, Object>> queryAllRealtyInfo(RealtyInfo realtyInfo) {
		return this.realtyInfoMapper.selectRealtyInfo(realtyInfo);
	}

	@Override
	public Map<String, Object> queryRealtyRoom(RealtyInfo realtyInfo) {
		List<Map<String, Object>> maps = this.realtyInfoMapper.selectRealtyRoom(realtyInfo);
		if(CollectionUtils.isEmpty(maps)) {
			return null;
		}

		return maps.get(0);
	}

	@Override
	public ServiceReslut addRealtyInfo(RealtyInfo realtyInfo) throws Exception {
		Map<String, Object> sessionUser = SecurityContext.getSessionUser();
		if(sessionUser == null) {
			return ServiceReslut.newServiceReslut(0, "获取登录用户信息失败");
		}

		realtyInfo.setCreateUserId((String) sessionUser.get("id"));

		CommonsMultipartFile cmf = realtyInfo.getFile();
		if(cmf != null) {
			FileItem item = cmf.getFileItem();
			String fileName = item.getName();
			String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
			String newFileName = UUID.randomUUID().toString().replaceAll("-", "") + "." + fileExt;
			String newFilePath = "product/" + newFileName;
			File file = new File(Const.DIR_UPLOAD_BASE + newFilePath);
			item.write(file);
			// 设置图片路径
			realtyInfo.setPicPath(newFilePath);
		}

		realtyInfo.setId(UUID.randomUUID().toString().replaceAll("-", ""));
		realtyInfo.setState("1");
		realtyInfo.setCreateTime(new Date());

		saveRooms(realtyInfo.getRoomNum(), realtyInfo);

		return ServiceReslut.newServiceReslut(realtyInfoMapper.insertRealtyInfo(realtyInfo), "");
	}


	/**
	 * 新增roomNum
	 * @param roomNums
	 * @param realtyInfo
	 */
	public void saveRooms(String roomNums, RealtyInfo realtyInfo) {
		if(StringUtils.isBlank(roomNums)) {
			return;
		}

		String[] rooms = StringUtils.split(roomNums, ",");
		String[] roomState = StringUtils.split(realtyInfo.getRoomState(), ",");

		if(rooms.length != roomState.length) {
			return;
		}

		RealtyRoomModel realtyRoomModel = null;

		for (int i = 0; i < rooms.length; i++) {
			realtyRoomModel = new RealtyRoomModel();
			realtyRoomModel.setId(UUID.randomUUID().toString().replaceAll("-", ""));
			realtyRoomModel.setRealtyId(realtyInfo.getId());
			realtyRoomModel.setRoomNum(rooms[i]);
			realtyRoomModel.setState(roomState[i]);
			realtyRoomModel.setCreateTime(new Date());

			realtyInfo.setRoomId(realtyRoomModel.getId());
			realtyRoomMapper.insertRealtyRoom(realtyRoomModel);
		}
	}

	@Override
	public ServiceReslut updateRealtyInfo(RealtyInfo realtyInfo) throws Exception {

		CommonsMultipartFile cmf = realtyInfo.getFile();
		if(cmf != null) {
			FileItem item = cmf.getFileItem();
			String fileName = item.getName();
			String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
			if(StringUtils.isNoneBlank(fileExt)) {
				String newFileName = UUID.randomUUID().toString().replaceAll("-", "") + "." + fileExt;
				String newFilePath = "product/" + newFileName;
				File file = new File(Const.DIR_UPLOAD_BASE + newFilePath);
				item.write(file);
				// 设置图片路径
				realtyInfo.setPicPath(newFilePath);
			}
		}

		//更新公寓房间号
		if(StringUtils.equals(realtyInfo.getTypeCode(), "HOUSE")) {

			JSONArray updateRooms = JSONArray.parseArray(realtyInfo.getUpdateRooms());
			if(updateRooms.size() == 0) {
				return ServiceReslut.newServiceReslut(0, "");
			}
			JSONObject jsonObject = updateRooms.getJSONObject(0);
			RealtyRoomModel realtyRoomModel = new RealtyRoomModel();
			realtyRoomModel.setRealtyId(realtyInfo.getId());
			realtyRoomModel.setRoomNum(jsonObject.getString("roomNum"));
			realtyRoomModel.setUpdateTime(new Date());
			if(StringUtils.isBlank(realtyRoomModel.getRealtyId())) {
				return ServiceReslut.newServiceReslut(0, "");
			}
			realtyRoomMapper.updateRealtyRoom(realtyRoomModel);
		}

		if(StringUtils.isNoneBlank(realtyInfo.getAddRoomNums()) && StringUtils.equals(realtyInfo.getTypeCode(), "BUILD")) {
			saveRooms(realtyInfo.getAddRoomNums(), realtyInfo);
		}

		if(StringUtils.equals(realtyInfo.getTypeCode(), "BUILD")) {
			//更新房间信息
			updateRealtyRooms(realtyInfo);
		}

		realtyInfo.setUpdateTime(new Date());
		setRoomNums(realtyInfo);
		return ServiceReslut.newServiceReslut(realtyInfoMapper.updateRealtyInfo(realtyInfo), "");
	}

	/**
	 * 设置房间号
	 */
	private void setRoomNums(RealtyInfo realtyInfo) {
		if(realtyInfo != null) {
			RealtyRoomModel realtyRoomModel = new RealtyRoomModel();
			realtyRoomModel.setRealtyId(realtyInfo.getId());
			List<Map<String, Object>> rooms = realtyRoomMapper.selectRealtyRoom(realtyRoomModel);
			if(rooms!=null && rooms.size()>0) {
				String roomNums = "";
				for (Map<String, Object> room : rooms) {
					roomNums += room.get("roomNum") + ",";
				}

				realtyInfo.setRoomNum(StringUtils.substring(roomNums, 0, roomNums.length()-1));
			}
		}
	}

	//更新房间信息
	private void updateRealtyRooms(RealtyInfo realtyInfo) {
		//删除房间
		if(StringUtils.isNoneBlank(realtyInfo.getDelRooms())) {
			String[] ids = StringUtils.split(realtyInfo.getDelRooms(), ",");
			RealtyRoomModel delRoom = null;
			for (String id : ids) {
				delRoom = new RealtyRoomModel();
				delRoom.setId(id);
				delRoom.setState("0");		//删除状态
				if(StringUtils.isBlank(delRoom.getId())) {
					continue;
				}
				realtyRoomMapper.updateRealtyRoom(delRoom);
			}
		}

		if(StringUtils.isNoneBlank(realtyInfo.getUpdateRooms())) {
			JSONArray updateRooms = JSONArray.parseArray(realtyInfo.getUpdateRooms());
			RealtyRoomModel updateRoom = null;
			JSONObject jsonObject = null;
			for (int i = 0; i < updateRooms.size(); i++) {
				updateRoom = new RealtyRoomModel();
				jsonObject = updateRooms.getJSONObject(i);
				updateRoom.setId(jsonObject.getString("id"));
				updateRoom.setUpdateTime(new Date());
				updateRoom.setRoomNum(jsonObject.getString("roomNum"));
				updateRoom.setState(jsonObject.getString("state"));

				if(StringUtils.isBlank(updateRoom.getId())) {
					continue;
				}
				realtyRoomMapper.updateRealtyRoom(updateRoom);
			}
		}
	}

	@Override
	public ServiceReslut deleteRealtyInfo(RealtyInfo realtyInfo) {
		realtyInfo.setState("0");		//删除状态
		realtyInfo.setUpdateTime(new Date());
		return ServiceReslut.newServiceReslut(realtyInfoMapper.updateRealtyInfo(realtyInfo), "");
	}

	@Override
	public void importRealty(MultipartHttpServletRequest request) {
		try {
			MultipartFile file = request.getFile("file");
			if(file == null) {
				throw new BusinessException("导入失败，导入文件为空", 400, null);
			}
			List<Map<String, String>> datas = JExcelReadUtils.readExcelSheet1(file.getInputStream(), -1, 2, -1);
			if(CollectionUtils.isEmpty(datas)) {
				throw new BusinessException("导入失败，内容为空", 400, null);
			}

			if(!JExcelReadUtils.checkImprtExcelFormat(datas.get(0), excel_cloum_names)) {
				throw new BusinessException("导入失败，excle 模版错误", 400, null);
			}

			List<RealtyInfo> realtyInfos = createRealtyList(datas);
			if(CollectionUtils.isEmpty(realtyInfos)) {
				throw new BusinessException("导入失败，内容为空", 400, null);
			}

			for (RealtyInfo realtyInfo : realtyInfos) {
				saveRooms(realtyInfo.getRoomNum(), realtyInfo);
				realtyInfoMapper.insertRealtyInfo(realtyInfo);
			}
		} catch (Exception e) {
			if (e instanceof BusinessException) {
				throw new BusinessException(e);
			} else {
				throw new BusinessException("导入失败", 400, null);
			}
		}
	}

	@Override
	public void importRealtyPic(MultipartHttpServletRequest request) {
		try {
			MultipartFile zipFile = request.getFile("file");
			if(zipFile == null) {
				throw new BusinessException("导入失败，导入文件为空", 400, null);
			}
			//获得文件名
			String zipFileName = zipFile.getOriginalFilename();
			//检查文件
			if(!StringUtils.endsWith(zipFileName, ".zip")){
				throw new BusinessException("导入图片失败，格式错误，只支持zip文件导入");
			}

			ZipInputStream zis=new ZipInputStream(zipFile.getInputStream(), Charset.forName("GBK"));
			ZipEntry zipEntry = null;
			byte[] buffer = new byte[512];//缓冲器
			int readLength = 0;//每次读出来的长度

			String fileName = "";
			String fileExt = "";
			Map<String, Object> realtyInfo = null;
			String[] paras = null;
			RealtyInfo realtyInfoModel = null;
			while ((zipEntry=zis.getNextEntry())!=null){
				if(!zipEntry.isDirectory()){//若是文件
					fileName = zipEntry.getName();
					fileExt = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
//					if(!StringUtils.equals(fileExt, "jpg")) {
//						continue;
//					}
					paras = StringUtils.split(StringUtils.substring(fileName, 0, fileName.lastIndexOf(".")), "_");
					if(paras.length != 3) {
						continue;
					}
					realtyInfo = getRealtyByCB(paras[0], paras[1], paras[2]);
					if(realtyInfo == null) {
						continue;
					}
					fileName = UUID.randomUUID().toString().replaceAll("-", "") + "." + fileExt;
					File file = ZipUtil.createFile(Const.DIR_UPLOAD_BASE + "/product", fileName);
					OutputStream os=new FileOutputStream(file);
					while ((readLength=zis.read(buffer,0,500))!=-1){
						os.write(buffer,0,readLength);
					}
					os.close();

					realtyInfoModel = new RealtyInfo();
					realtyInfoModel.setId(realtyInfo.get("id").toString());
					realtyInfoModel.setPicPath("product/" + fileName);
					this.updateRealtyInfo(realtyInfoModel);
				}
			}

		}catch (Exception e) {
			e.printStackTrace();
			if (e instanceof BusinessException) {
				throw new BusinessException(e);
			} else {
				throw new BusinessException("导入失败", 400, null);
			}
		}
	}

	private List<RealtyInfo> createRealtyList(List<Map<String, String>> datas) {
		List<RealtyInfo> realtyInfos = new ArrayList<>();

		for (int i = 1; i < datas.size(); i++) {
			realtyInfos.add(createRealty(datas.get(i), i));
		}

		return realtyInfos;
	}

	private RealtyInfo createRealty(Map<String, String> data, int row) {
		if(StringUtils.isBlank(data.get("0"))) {
			throw new BusinessException(String.format("第[%s]条导入失败，客户名称不能为空", row, data.get("0")), 400, null);
		}

		Map<String, Object> customerMap = customerService.queryCustomerByName(data.get("0"));
		if(customerMap == null) {
			throw new BusinessException(String.format("第[%s]条导入失败，客户名称[%s] 不存在",row, data.get("0")), 400, null);
		}

		RealtyInfo realtyInfo = new RealtyInfo();
		realtyInfo.setCustomerId(customerMap.get("id").toString());
		realtyInfo.setCustomerName(customerMap.get("name").toString());

		String typeName = data.get("1");
		String typeCode = "";
		if(StringUtils.equals(typeName, "公寓")) {
			typeCode = "HOUSE";
		} else if(StringUtils.equals(typeName, "一栋")) {
			typeCode = "BUILD";
		}
		if(StringUtils.isBlank(typeCode)) {
			throw new BusinessException(String.format("第[%s]条导入失败，客户名称[%s] ，公寓类型错误", row, data.get("0")), 400, null);
		}
		realtyInfo.setTypeCode(typeCode);
		realtyInfo.setTypeValue(typeName);

		if(StringUtils.isBlank(data.get("2"))) {
			throw new BusinessException(String.format("第[%s]条导入失败，客户名称[%s] 楼盘名称", row, data.get("0")), 400, null);
		}
		realtyInfo.setBuildingName(data.get("2"));
		String roomNum = data.get("3");
		if(StringUtils.isBlank(roomNum)) {
			throw new BusinessException(String.format("第[%s]条导入失败，客户名称[%s]，楼盘[%s] 房间号不能为空",row, data.get("0"),realtyInfo.getBuildingName()), 400, null);
		}
		try {
			setRealtyRoomNum(roomNum, realtyInfo);
		} catch (Exception e) {
			throw new BusinessException(String.format("第[%s]条导入失败，房间号[%s]解析失败",row, roomNum,realtyInfo.getBuildingName()), 400, null);
		}

		realtyInfo.setBuildingAddress(data.get("4"));
		realtyInfo.setBuyPrice(new BigDecimal(data.get("6")));
		realtyInfo.setBuildDate(data.get("7"));

		String gzName = data.get("8");
		String gzCode = getGzCode(gzName);
		if(StringUtils.isBlank(gzCode)) {
			throw new BusinessException(String.format("第[%s]条导入失败，客户名称[%s]，楼盘[%s] 构造错误", row, data.get("0"),realtyInfo.getBuildingName()), 400, null);
		}
		realtyInfo.setStructureCode(gzCode);
		realtyInfo.setStructureValue(gzName);
		realtyInfo.setFloor(data.get("9"));
		realtyInfo.setInsure(data.get("10"));
		realtyInfo.setArea(data.get("11"));
		realtyInfo.setGdTax(new BigDecimal(data.get("12")));
		realtyInfo.setManageCost(new BigDecimal(data.get("13")));
		realtyInfo.setFixCost(new BigDecimal(data.get("14")));

		String landArea = data.get("15");
		if(StringUtils.isNotBlank(landArea)) {
			try {
				String[] landAreaArray = StringUtils.split(landArea, "#");
				realtyInfo.setLandArea(landAreaArray[0]);
				realtyInfo.setLandAreaTypeCode(getAreaCode(landAreaArray[1]));
				realtyInfo.setLandAreaTypeName(landAreaArray[1]);
			} catch (Exception e) {
				throw new BusinessException(String.format("第[%s]条导入失败，土地面积[%s]解析失败",row, landArea,realtyInfo.getBuildingName()), 400, null);
			}
		}

		String buildArea = data.get("16");
		if(StringUtils.isNotBlank(buildArea)) {
			try {
				String[] buildAreaArray = StringUtils.split(buildArea, "#");
				realtyInfo.setBuildArea(buildAreaArray[0]);
				realtyInfo.setBuildAreaTypeCode(getAreaCode(buildAreaArray[1]));
				realtyInfo.setBuildAreaTypeName(buildAreaArray[1]);
			} catch (Exception e) {
				throw new BusinessException(String.format("第[%s]条导入失败，建筑面积[%s]解析失败",row, buildArea,realtyInfo.getBuildingName()), 400, null);
			}
		}

		realtyInfo.setBuildRate(data.get("17"));
		realtyInfo.setPlotRate(data.get("18"));
		realtyInfo.setAreaUse(data.get("19"));

		Map<String, Object> sessionUser = SecurityContext.getSessionUser();
		realtyInfo.setCreateUserId((String) sessionUser.get("id"));

		realtyInfo.setId(UUID.randomUUID().toString().replaceAll("-", ""));
		realtyInfo.setState("1");
		realtyInfo.setCreateTime(new Date());

		return realtyInfo;
	}

	private String getAreaCode(String areaName) {
		if(StringUtils.equals(areaName, "壁芯")) {
			return "BX";
		} else if(StringUtils.equals(areaName, "登記")) {
			return "DJ";
		}

		return null;
	}

	private void setRealtyRoomNum(String rooms, RealtyInfo realtyInfo) {
		String[] roomNums = StringUtils.split(rooms, ",");

		String roomNum = "" ;
		String roomState = "";

		String[] room = null;
		for (String _room : roomNums) {
			room = StringUtils.split(_room, "#");
			roomNum += room[0] + ",";

			switch (room[1]) {
				case "空房":
					roomState += "1,";
					break;
				case "租赁中":
					roomState += "2,";
					break;
				case "装修中":
					roomState += "3,";
					break;
			}
		}

		realtyInfo.setRoomNum(StringUtils.substring(roomNum, 0, roomNum.length()-1));
		realtyInfo.setRoomState(StringUtils.substring(roomState, 0, roomState.length()-1));
	}

	/**
	 * 初始化客户来源map
	 */
	private void initGzMap() {
		DictModel dictModel = new DictModel();
		dictModel.setType("gzyx");
		gzCodeMap = dictService.queryDict(dictModel);
	}

	private String getGzCode(String name) {
		if(org.springframework.util.CollectionUtils.isEmpty(gzCodeMap)) {
			initGzMap();
		}

		if(org.springframework.util.CollectionUtils.isEmpty(gzCodeMap)) {
			throw new BusinessException("导入失败，查询构造失败", 400, null);
		}

		for (Map<String, Object> dataMap : gzCodeMap) {
			if(StringUtils.equals(dataMap.get("value").toString(), name)) {
				return dataMap.get("code").toString();
			}
		}

		return null;
	}

	/**
	 * 查询房间信息
	 * @param cutomerName
	 * @param buildingName
	 * @param roomNum
	 * @return
	 */
	private Map<String, Object> getRealtyByCB(String cutomerName, String buildingName, String roomNum) {
		RealtyInfo realtyInfo = new RealtyInfo();
		realtyInfo.setCustomerNameEq(cutomerName);
		realtyInfo.setBuildingNameEq(buildingName);
		realtyInfo.setRoomNumEq(roomNum);
		List<Map<String, Object>> realtyMaps = queryAllRealtyInfo(realtyInfo);

		if(CollectionUtils.isEmpty(realtyMaps)) {
			return null;
		}

		return realtyMaps.get(0);
	}
}
